﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Tiens.NotificationHub.Abstractions.Store;
using Tiens.NotificationHub.Services;

namespace Tiens.NotificationHub.Core.Services
{
    public class InRedisAppConnectionManager:IAppConnectionManager
    { 
        private readonly IAppConnectionStore _appConnectionStore;

        public InRedisAppConnectionManager(IAppConnectionStore appConnectionStore)
        {
            _appConnectionStore = appConnectionStore;
        }

        public Task JoinAsync(string userId, string appId, string connectionId)
            => _appConnectionStore.AddConnectAsync(userId, appId, connectionId);

        public Task QuitAsync(string groupName, string appId, string connectionId)
            => _appConnectionStore.RemoveConnectAsync(groupName, appId, connectionId);

        public async Task<IEnumerable<string>> GroupsByAppIdAsync(string appId)
        {
            var connections = await _appConnectionStore.GetConnectionsAsync(appId);

            return connections.Select(x => x.Key);
        }

        public async Task<IEnumerable<string>> UsersOnline(string appId)
        {
            var connections = await _appConnectionStore.GetConnectionsAsync(appId);

            return connections.Where(x => x.Value.AppId.Equals(appId) && x.Value.ConnectionIds.Any())
                .Select(x => x.Value.UserId);
        }

        public async Task<int> UsersOnlineNumber(string appId)
        {
            var connections = await _appConnectionStore.GetConnectionsAsync(appId);

            return connections.Count(x => x.Value.AppId.Equals(appId) && x.Value.ConnectionIds.Any());
        }

        public async Task<IEnumerable<string>> ConnectionIds(string appId)
        {
            var connections = await _appConnectionStore.GetConnectionsAsync(appId);

            return connections.Where(x => x.Value.AppId.Equals(appId)).SelectMany(x => x.Value.ConnectionIds);
        }

        public async Task<IEnumerable<string>> ConnectionIds(string userId, string appId)
        {
            var connections = await _appConnectionStore.GetConnectionsAsync(appId);

            return connections.Where(x => x.Key.Equals(userId) && x.Value.AppId.Equals(appId))
                .SelectMany(x => x.Value.ConnectionIds);
        }
    }
}
